import json
import re
import logging
from django.contrib.auth import logout
from django.http import JsonResponse, request
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from areas.serializers import AreaModelSerializer
from meiduo_mall.utils.views import LoginRequiredMixin
logger = logging.getLogger('django')
from django.views import View
from areas.models import Area
from django import http
from django.core.cache import cache
from users.models import Address, User


class Provinces(View):
    def get(self,request):

        province_list = cache.get('province_list')

        if not province_list:

            try:
                province_data_list = Area.objects.filter(parent__isnull=True)

                province_list = []

                for province_data in province_data_list:

                    province_list.append({'id':province_data.id,
                                 'name':province_data.name})

                cache.set('province_list',json.dumps(province_list),3600)

            except Exception as e:
                return JsonResponse({'code': 400,
                                     'errmsg': '读取数据库失败'})
        else:
            province_list = json.loads(province_list)
        return JsonResponse({'code':0,
                             'errmsg':'ok',
                             'province_list':province_list})

class Subs(View):

    def get(self,request,pk):

        sub_data = cache.get('sub_data' + pk)

        if not sub_data:

            try:

                list = []

                subs_list = Area.objects.filter(parent=pk)

                parent_data = Area.objects.get(id=pk)

                for subs in subs_list:
                    list.append({'id':subs.id,
                                 'name':subs.name})
                sub_data = {'id':parent_data.id,
                            "name":parent_data.name,
                            'subs':list}

                cache.set('sub_data' + pk, sub_data, 3600)

            except Exception as e:
                return JsonResponse({'code':400,
                                     'errmag':'市级信息错误'})

            return JsonResponse({'code': 0,
                                 'errmag': 'ok',
                                 'sub_data':sub_data})

#
# class ProvinceAreasView(View):
#     """省级地区"""
#
#     def get(self, request):
#         """提供省级地区数据
#         1.查询省级数据
#         2.序列化省级数据
#         3.响应省级数据
#         4.补充缓存逻辑
#         """
#         # 增加: 判断是否有缓存
#         province_list = cache.get('province_list')
#
#         if not province_list:
#             try:
#                 province_model_list = Area.objects.filter(parent__isnull=True)
#
#                 province_list = []
#                 for province_model in province_model_list:
#                     province_list.append({'id': province_model.id,
#                                           'name': province_model.name})
#
#                 # 增加: 缓存省级数据
#                 cache.set('province_list', province_list, 3600)
#             except Exception as e:
#                 return http.JsonResponse({'code': 400,
#                                           'errmsg': '省份数据错误'})
#
#         # 3.返回整理好的省级数据
#         return http.JsonResponse({'code': 0,
#                                   'errmsg': 'OK',
#                                   'province_list': province_list})
#
# class SubAreasView(View):
#     """子级地区：市和区县"""
#
#     def get(self, request, pk):
#         """提供市或区地区数据
#         1.查询市或区数据
#         2.序列化市或区数据
#         3.响应市或区数据
#         4.补充缓存数据
#         """
#         # 判断是否有缓存
#         sub_data = cache.get('sub_area_' + pk)
#
#         if not sub_data:
#
#             # 1.查询市或区数据
#             try:
#                 sub_model_list = Area.objects.filter(parent=pk)
#                 # 查询市或区的父级
#                 parent_model = Area.objects.get(id=pk)
#
#                 # 2.序列化市或区数据
#                 sub_list = []
#                 for sub_model in sub_model_list:
#                     sub_list.append({'id': sub_model.id,
#                                      'name': sub_model.name})
#
#                 sub_data = {
#                     'id': parent_model.id,  # pk
#                     'name': parent_model.name,
#                     'subs': sub_list
#                 }
#
#                 # 缓存市或区数据
#                 cache.set('sub_area_' + pk, sub_data, 3600)
#             except Exception as e:
#                 return http.JsonResponse({'code': 400,
#                                           'errmsg': '城市或区县数据错误'})
#
#         # 3.响应市或区数据 ok: 0
#         return http.JsonResponse({'code': 0,
#                                   'errmsg': 'OK',
#                                   'sub_data': sub_data})

# class AddressCreate(View):
#     def post(self,request):
#
#         try:
#             count = Address.objects.filter(user=request.user,
#                                            is_deleted=False)
#         except Exception as e:
#             return JsonResponse({'code':400,
#
#                                  'errmsg':'获取地址数据出错'})
#
#         # 判断是否超过地址上限：最多20个
#         if count >= 20:
#             return http.JsonResponse({'code': 400,
#                                       'errmsg': '超过地址数量上限'})
#
#
#         dict = json.loads(request.body.decode())
#         receiver = dict.get('receiver')
#         province_id = dict.get('province_id')
#         city_id = dict.get('city_id')
#         district_id = dict.get('district_id')
#         place = dict.get('place')
#         mobile = dict.get('mobile')
#         tel = dict.get('tel')
#         email = dict.get('email')
#
#         if not all([receiver,province_id,city_id,district_id,place,mobile,tel,email]):
#             return JsonResponse({'code':400,
#                                  'errmsg':'缺少必传的参数'})
#         if not re.match(r'^1[3-9]\d{9}/$',mobile):
#             return JsonResponse({'code':400,
#                                  'errmsg':'手机号格式错误'})
#         if tel:
#             if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
#                 return http.JsonResponse({'code': 400,
#                                           'errmsg': '参数tel有误'})
#         if email:
#             if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
#                 return http.JsonResponse({'code': 400,
#                                           'errmsg': '参数email有误'})
#
#         try:
#             address = Address.objects.create(
#                 user=request.user,
#                 title=receiver,
#                 receiver=receiver,
#                 province_id=province_id,
#                 city_id=city_id,
#                 district_id=district_id,
#                 place=place,
#                 mobile=mobile,
#                 tel=tel,
#                 email=email
#             )
#
#             if not request.user.default_address:
#                 request.user.default_address = address
#                 request.user.save()
#
#         except Exception as e:
#             logger.info(e)
#             return JsonResponse({'code':400,
#                                  'errmsg':'保存数据库失败'})
#
#         address_dict = {
#             "id": address.id,
#             "title": address.title,
#             "receiver": address.receiver,
#             "province": address.province.name,
#             "city": address.city.name,
#             "district": address.district.name,
#             "place": address.place,
#             "mobile": address.mobile,
#             "tel": address.tel,
#             "email": address.email
#         }
#
#         return JsonResponse({'code': 0,
#                              'errmsg': 'ok',
#                              'address':address_dict})

class CreateAddressView(View):
    """新增地址"""

    def post(self, request):
        """实现新增地址逻辑"""

        # 获取地址个数:
        try:
           count = Address.objects.filter(user=request.user,
                                       is_deleted=False).count()
        except Exception as e:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '获取地址数据出错'})
        # 判断是否超过地址上限：最多20个
        if count >= 20:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '超过地址数量上限'})

        # 接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '缺少必传参数'})


        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '参数mobile有误'})

        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.JsonResponse({'code': 400,
                                          'errmsg': '参数tel有误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.JsonResponse({'code': 400,
                                          'errmsg': '参数email有误'})

        # 保存地址信息
        try:
            address = Address.objects.create(
                user=request.user,
                title = receiver,
                receiver = receiver,
                province_id = province_id,
                city_id = city_id,
                district_id = district_id,
                place = place,
                mobile = mobile,
                tel = tel,
                email = email
            )

            # 设置默认地址
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()

        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': 400,
                                      'errmsg': '新增地址失败'})

        # 新增地址成功，将新增的地址响应给前端实现局部刷新
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应保存结果
        return http.JsonResponse({'code': 0,
                                  'errmsg': '新增地址成功',
                                  'address':address_dict})

class AddressView(View):
    """用户收货地址"""

    def get(self, request):
        """提供地址管理界面
        """
        # 获取所有的地址:
        addresses = Address.objects.filter(user=request.user,
                                           is_deleted=False)

        # 创建空的列表
        address_dict_list = []
        # 遍历
        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }

            # 将默认地址移动到最前面
            default_address = request.user.default_address
            if default_address.id == address.id:
                  # 查询集 addresses 没有 insert 方法
                address_dict_list.insert(0, address_dict)
            else:
                address_dict_list.append(address_dict)

        default_id = request.user.default_address_id

        return http.JsonResponse({'code':0,
                                  'errmsg':'ok',
                                  'addresses':address_dict_list,
                                  'default_address_id':default_id})

class UpdateDestroyAddressView(View):
    """修改和删除地址"""

    def put(self, request, address_id):
        """修改地址"""
        # 接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '缺少必传参数'})


        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '参数mobile有误'})

        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.JsonResponse({'code': 400,
                                          'errmsg': '参数tel有误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.JsonResponse({'code': 400,
                                          'errmsg': '参数email有误'})

        # 判断地址是否存在,并更新地址信息
        try:
            Address.objects.filter(id=address_id).update(
                user = request.user,
                title = receiver,
                receiver = receiver,
                province_id = province_id,
                city_id = city_id,
                district_id = district_id,
                place = place,
                mobile = mobile,
                tel = tel,
                email = email
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': 400,
                                      'errmsg': '更新地址失败'})

        # 构造响应数据
        address = Address.objects.get(id=address_id)
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应更新地址结果
        return http.JsonResponse({'code': 0,
                                  'errmsg': '更新地址成功',
                                  'address': address_dict})

    def delete(self, request, address_id):
        """删除地址"""
        try:
            # 查询要删除的地址
            address = Address.objects.get(id=address_id)

            # 将地址逻辑删除设置为True
            address.is_deleted = True
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': 400,
                                      'errmsg': '删除地址失败'})

        # 响应删除地址结果
        return http.JsonResponse({'code': 0,
                                  'errmsg': '删除地址成功'})

class DefaultAddressView(View):
    def put(self,request,address_id):
        try:
            address = Address.objects.get(id=address_id)
            request.user.default_address = address
            request.user.save()
        except Exception as e:
            return JsonResponse({'code':400,
                                 'errmsg':'设置默认地址失败'})
        return JsonResponse({'code':0,
                                 'errmsg':'ok'})

# class DefaultAddressView(View):
#     """设置默认地址"""
#
#     def put(self, request, address_id):
#         """设置默认地址"""
#         try:
#             # 接收参数,查询地址
#             address = Address.objects.get(id=address_id)
#
#             # 设置地址为默认地址
#             request.user.default_address = address
#             request.user.save()
#         except Exception as e:
#             logger.error(e)
#             return http.JsonResponse({'code': 400,
#                                       'errmsg': '设置默认地址失败'})
#
#         # 响应设置默认地址结果
#         return http.JsonResponse({'code': 0,
#                                   'errmsg': '设置默认地址成功'})
class UpdateTitleAddressView(View):
    def put(self,request,address_id):

        dict = json.loads(request.body.decode())
        title = dict.get("title")
        try:
            address = Address.objects.get(id=address_id)

            address.title = title
            address.save()
        except Exception as e:
            return JsonResponse({'code':400,
                                  'errmsg': '修改地址标题错失败'})
        return JsonResponse({'code': 0,
                             'errmsg': 'ok'})

# class UpdateTitleAddressView(View):
#     """设置地址标题"""
#
#     def put(self, request, address_id):
#         """设置地址标题"""
#         # 接收参数：地址标题
#         json_dict = json.loads(request.body.decode())
#         title = json_dict.get('title')
#
#         try:
#             # 查询地址
#             address = Address.objects.get(id=address_id)
#
#             # 设置新的地址标题
#             address.title = title
#             address.save()
#         except Exception as e:
#             logger.error(e)
#             return http.JsonResponse({'code': 400,
#                                       'errmsg': '设置地址标题失败'})
#
#         # 4.响应删除地址结果
#         return http.JsonResponse({'code': 0,
#                                   'errmsg': '设置地址标题成功'})

class ChangePasswordView(LoginRequiredMixin, View):
    def put(self,request):
        dict = json.loads(request.body.decode())
        old_password = dict.get('old_password')
        new_password = dict.get('new_password')
        new_password2 = dict.get('new_password2')

        if not all([old_password,new_password,new_password2]):
            return JsonResponse({'code':400,'errmag':'缺少必传参数'})

        result = request.user.check_password(old_password)
        if not result:
            return JsonResponse({'code':400,
                                 'errmsg':'密码验证失败'})

        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return JsonResponse({'code':400,
                                      'errmsg':'密码最少8位,最长20位'})

        if new_password != new_password2:
            return JsonResponse({'code':400,
                                      'errmsg':'两次输入密码不一致'})

        try:
            request.user.set_password(new_password2)
            request.user.save()
        except Exception as e:
            return JsonResponse({'code':400,
                                 'errmsg':'修改密码失败'})
        logout(request)

        response =  JsonResponse({'code':0,
                             'errmsg':'ok'})
        response.delete_cookie('username')

        return response
# class ChangePasswordView(LoginRequiredMixin, View):
#     """修改密码"""
#
#     def put(self, request):
#         """实现修改密码逻辑"""
#         # 接收参数
#         dict = json.loads(request.body.decode())
#         old_password = dict.get('old_password')
#         new_password = dict.get('new_password')
#         new_password2 = dict.get('new_password2')
#
#         # 校验参数
#         if not all([old_password, new_password, new_password2]):
#            return http.JsonResponse({'code':400,
#                                      'errmsg':'缺少必传参数'})
#
#
#         result = request.user.check_password(old_password)
#         if not result:
#             return http.JsonResponse({'code':400,
#                                       'errmsg':'原始密码不正确'})
#
#         if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
#             return http.JsonResponse({'code':400,
#                                       'errmsg':'密码最少8位,最长20位'})
#
#         if new_password != new_password2:
#             return http.JsonResponse({'code':400,
#                                       'errmsg':'两次输入密码不一致'})
#
#         # 修改密码
#         try:
#             request.user.set_password(new_password)
#             request.user.save()
#         except Exception as e:
#             logger.error(e)
#             return http.JsonResponse({'code':400,
#                                       'errmsg':'修改密码失败'})
#
#         # 清理状态保持信息
#         logout(request)
#
#         response = http.JsonResponse({'code':0,
#                                       'errmsg':'ok'})
#
#         response.delete_cookie('username')
#
#         # # 响应密码修改结果：重定向到登录界面
#         return response

from users.models import User

user = User.objects.get(id=1)

from users.serializers import UserSerializer

serializer = UserSerializer(user)

serializer.data

class AddressGenericAPIView(GenericAPIView):
    """用户收货地址"""

    queryset = Address.objects.all()

    serializer_class = AreaModelSerializer

    def get(self, request,user):
        """提供地址管理界面
        """
        # 获取所有的地址:
        address_id = self.get_queryset()

        # 2.创建序列化器，并传递查询结果集（设置many=True）
        serializer = self.get_serializer(address_id)
        # 3.返回响应 serializers.data 就是字典列表
        return Response(serializer.data)